package com.forum.module.system.controller.admin.file;

import cn.hutool.core.collection.CollUtil;
import com.forum.framework.common.exception.util.ServiceExceptionUtils;
import com.forum.framework.common.pojo.DataResult;
import com.forum.framework.common.pojo.PageResult;
import com.forum.module.system.controller.admin.file.vo.FilePageReqVO;
import com.forum.module.system.controller.admin.file.vo.FileRespVO;
import com.forum.module.system.controller.admin.role.vo.RolePageReqVO;
import com.forum.module.system.controller.admin.role.vo.RoleRespVO;
import com.forum.module.system.convert.file.FileConvert;
import com.forum.module.system.convert.role.RoleCovert;
import com.forum.module.system.dal.dataobject.file.FileDO;
import com.forum.module.system.dal.dataobject.role.RoleDO;
import com.forum.module.system.service.file.FileService;
import com.forum.module.system.util.uuid.UUID;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

import static com.forum.framework.common.pojo.DataResult.success;
import static com.forum.module.system.enums.ErrorCodeConstants.*;


/**
 * 功能:文件上传下载
 * 作者:ouyzh
 * 日期:2025/2/24 7:14
 */
@Tag(name = "管理后台 - 文件")
@RestController("adminFileController")
@RequestMapping("/system/file")
public class FileController {
    @Value("${app.upload-dir}")
    private String uploadDir;

    private final FileService fileService;

    public FileController(FileService fileService) {
        this.fileService = fileService;
    }

    @PostMapping("/upload")
    public DataResult<String> uploadFile(@RequestParam("file") MultipartFile file) {
        try {
            // 生成唯一文件名，防止重复和路径遍历
            String fileName = generateUniqueFileName(file.getOriginalFilename());

            // 创建上传目录（如果不存在）
            Path uploadPath = Paths.get(uploadDir);
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
            }

            // 保存文件
            Path targetLocation = uploadPath.resolve(fileName);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            // 生成访问URL
            String fileUrl = ServletUriComponentsBuilder.fromCurrentContextPath()
                    .path("/admin-api/system/file/download")
                    .queryParam("filename", fileName)
                    .toUriString();

            FileDO fileDO = new FileDO().setFilename(file.getOriginalFilename()).setFilesize(String.valueOf(file.getSize()))
                    .setFiletype(file.getContentType()).setFilepath(fileUrl).setStatus(1).setRemark("用户上传");
            fileService.saveFileSnapshot(fileDO);

            return DataResult.success(fileUrl);
        } catch (IOException e) {
            throw ServiceExceptionUtils.exception(FILE_UPLOAD_FAIL);
        }
    }

    @GetMapping("/download")
    public ResponseEntity<Resource> downloadFile(@RequestParam("filename") String filename) {
        try {
            Path filePath = Paths.get(uploadDir)
                    .resolve(filename)
                    .normalize()
                    .toAbsolutePath();

            Path uploadDirPath = Paths.get(uploadDir).normalize().toAbsolutePath();
            if (!filePath.startsWith(uploadDirPath)) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
            }

            Resource resource = new PathResource(filePath);
            if (!resource.exists() || !resource.isReadable()) {
                return ResponseEntity.notFound().build();
            }

            String contentType = Files.probeContentType(filePath);
            if (contentType == null) {
                contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
            }

            HttpHeaders headers = new HttpHeaders();

            headers.setContentType(MediaType.parseMediaType(contentType));

            ContentDisposition disposition = contentType.startsWith("image/")
                    ? ContentDisposition.inline().filename(resource.getFilename()).build()
                    : ContentDisposition.attachment().filename(resource.getFilename()).build();
            headers.setContentDisposition(disposition);

            return ResponseEntity.ok()
                    .headers(headers)
                    .contentLength(resource.contentLength())
                    .body(resource);
        } catch (Exception e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    @PostMapping("/page")
    @Operation(summary = "分页查询文件列表")
    public DataResult<PageResult<FileRespVO>> page(@RequestBody @Valid FilePageReqVO pageReqVO) {
        // 获得文件分页列表
        PageResult<FileDO> pageResult = fileService.getFilePage(pageReqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }

        return success(new PageResult<>(FileConvert.INSTANCE.covertList(pageResult.getList()), pageResult.getTotal()));
    }

    private String generateUniqueFileName(String originalFileName) {
        String safeFileName = StringUtils.cleanPath(originalFileName);
        String uuid = UUID.randomUUID().toString();
        return uuid + "_" + safeFileName;
    }
}


